home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1994 / MacHack 1994.toast / MacHack™ 1987-1994 / MacHack™ '87 / Source ƒ.sea / Source ƒ / emacs source ƒ / WORD.C < prev   
Encoding:
C/C++ Source or Header  |  1992-06-28  |  16.0 KB  |  533 lines  |  [TEXT/MARC]

  1. /*
  2.  * The routines in this file implement commands that work word or a
  3.  * paragraph at a time.  There are all sorts of word mode commands.  If I
  4.  * do any sentence mode commands, they are likely to be put in this file. 
  5.  */
  6.  
  7. #include        <stdio.h>
  8. #include        "estruct.h"
  9. #include    "edef.h"
  10.  
  11. /* Word wrap on n-spaces. Back-over whatever precedes the point on the current
  12.  * line and stop on the first word-break or the beginning of the line. If we
  13.  * reach the beginning of the line, jump back to the end of the word and start
  14.  * a new line.  Otherwise, break the line at the word-break, eat it, and jump
  15.  * back to the end of the word.
  16.  * Returns TRUE on success, FALSE on errors.
  17.  */
  18. wrapword(n)
  19.  
  20. int n;
  21.  
  22. {
  23.         register int cnt;    /* size of word wrapped to next line */
  24.     register int c;        /* charector temporary */
  25.  
  26.     /* backup from the <NL> 1 char */
  27.         if (!backchar(0, 1))
  28.             return(FALSE);
  29.  
  30.     /* back up until we aren't in a word,
  31.        make sure there is a break in the line */
  32.         cnt = 0;
  33.     while (((c = lgetc(curwp->w_dotp, curwp->w_doto)) != ' ')
  34.                 && (c != '\t')) {
  35.                 cnt++;
  36.                 if (!backchar(0, 1))
  37.                         return(FALSE);
  38.         /* if we make it to the beginning, start a new line */
  39.         if (curwp->w_doto == 0) {
  40.             gotoeol(FALSE, 0);
  41.             return(newline(0,1));
  42.         }
  43.         }
  44.  
  45.     /* delete the forward white space */
  46.         if (!forwdel(0, 1))
  47.                 return(FALSE);
  48.  
  49.     /* put in a end of line */
  50.         if (!newline(0, 1))
  51.                 return(FALSE);
  52.  
  53.     /* and past the first word */
  54.     while (cnt-- > 0) {
  55.         if (forwchar(FALSE, 1) == FALSE)
  56.             return(FALSE);
  57.     }
  58.         return(TRUE);
  59. }
  60.  
  61. /*
  62.  * Move the cursor backward by "n" words. All of the details of motion are
  63.  * performed by the "backchar" and "forwchar" routines. Error if you try to
  64.  * move beyond the buffers.
  65.  */
  66. backword(f, n)
  67. {
  68.         if (n < 0)
  69.                 return (forwword(f, -n));
  70.         if (backchar(FALSE, 1) == FALSE)
  71.                 return (FALSE);
  72.         while (n--) {
  73.                 while (inword() == FALSE) {
  74.                         if (backchar(FALSE, 1) == FALSE)
  75.                                 return (FALSE);
  76.                 }
  77.                 while (inword() != FALSE) {
  78.                         if (backchar(FALSE, 1) == FALSE)
  79.                                 return (FALSE);
  80.                 }
  81.         }
  82.         return (forwchar(FALSE, 1));
  83. }
  84.  
  85. /*
  86.  * Move the cursor forward by the specified number of words. All of the motion
  87.  * is done by "forwchar". Error if you try and move beyond the buffer's end.
  88.  */
  89. forwword(f, n)
  90. {
  91.         if (n < 0)
  92.                 return (backword(f, -n));
  93.         while (n--) {
  94. #if    NFWORD
  95.                 while (inword() != FALSE) {
  96.                         if (forwchar(FALSE, 1) == FALSE)
  97.                                 return (FALSE);
  98.                 }
  99. #endif
  100.                 while (inword() == FALSE) {
  101.                         if (forwchar(FALSE, 1) == FALSE)
  102.                                 return (FALSE);
  103.                 }
  104. #if    NFWORD == 0
  105.                 while (inword() != FALSE) {
  106.                         if (forwchar(FALSE, 1) == FALSE)
  107.                                 return (FALSE);
  108.                 }
  109. #endif
  110.         }
  111.     return(TRUE);
  112. }
  113.  
  114. /*
  115.  * Move the cursor forward by the specified number of words. As you move,
  116.  * convert any characters to upper case. Error if you try and move beyond the
  117.  * end of the buffer. Bound to "M-U".
  118.  */
  119. upperword(f, n)
  120. {
  121.         register int    c;
  122.  
  123.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  124.         return(rdonly());    /* we are in read only mode    */
  125.         if (n < 0)
  126.                 return (FALSE);
  127.         while (n--) {
  128.                 while (inword() == FALSE) {
  129.                         if (forwchar(FALSE, 1) == FALSE)
  130.                                 return (FALSE);
  131.                 }
  132.                 while (inword() != FALSE) {
  133.                         c = lgetc(curwp->w_dotp, curwp->w_doto);
  134.                         if (c>='a' && c<='z') {
  135.                                 c -= 'a'-'A';
  136.                                 lputc(curwp->w_dotp, curwp->w_doto, c);
  137.                                 lchange(WFHARD);
  138.                         }
  139.                         if (forwchar(FALSE, 1) == FALSE)
  140.                                 return (FALSE);
  141.                 }
  142.         }
  143.         return (TRUE);
  144. }
  145.  
  146. /*
  147.  * Move the cursor forward by the specified number of words. As you move
  148.  * convert characters to lower case. Error if you try and move over the end of
  149.  * the buffer. Bound to "M-L".
  150.  */
  151. lowerword(f, n)
  152. {
  153.         register int    c;
  154.  
  155.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  156.         return(rdonly());    /* we are in read only mode    */
  157.         if (n < 0)
  158.                 return (FALSE);
  159.         while (n--) {
  160.                 while (inword() == FALSE) {
  161.                         if (forwchar(FALSE, 1) == FALSE)
  162.                                 return (FALSE);
  163.                 }
  164.                 while (inword() != FALSE) {
  165.                         c = lgetc(curwp->w_dotp, curwp->w_doto);
  166.                         if (c>='A' && c<='Z') {
  167.                                 c += 'a'-'A';
  168.                                 lputc(curwp->w_dotp, curwp->w_doto, c);
  169.                                 lchange(WFHARD);
  170.                         }
  171.                         if (forwchar(FALSE, 1) == FALSE)
  172.                                 return (FALSE);
  173.                 }
  174.         }
  175.         return (TRUE);
  176. }
  177.  
  178. /*
  179.  * Move the cursor forward by the specified number of words. As you move
  180.  * convert the first character of the word to upper case, and subsequent
  181.  * characters to lower case. Error if you try and move past the end of the
  182.  * buffer. Bound to "M-C".
  183.  */
  184. capword(f, n)
  185. {
  186.         register int    c;
  187.  
  188.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  189.         return(rdonly());    /* we are in read only mode    */
  190.         if (n < 0)
  191.                 return (FALSE);
  192.         while (n--) {
  193.                 while (inword() == FALSE) {
  194.                         if (forwchar(FALSE, 1) == FALSE)
  195.                                 return (FALSE);
  196.                 }
  197.                 if (inword() != FALSE) {
  198.                         c = lgetc(curwp->w_dotp, curwp->w_doto);
  199.                         if (c>='a' && c<='z') {
  200.                                 c -= 'a'-'A';
  201.                                 lputc(curwp->w_dotp, curwp->w_doto, c);
  202.                                 lchange(WFHARD);
  203.                         }
  204.                         if (forwchar(FALSE, 1) == FALSE)
  205.                                 return (FALSE);
  206.                         while (inword() != FALSE) {
  207.                                 c = lgetc(curwp->w_dotp, curwp->w_doto);
  208.                                 if (c>='A' && c<='Z') {
  209.                                         c += 'a'-'A';
  210.                                         lputc(curwp->w_dotp, curwp->w_doto, c);
  211.                                         lchange(WFHARD);
  212.                                 }
  213.                                 if (forwchar(FALSE, 1) == FALSE)
  214.                                         return (FALSE);
  215.                         }
  216.                 }
  217.         }
  218.         return (TRUE);
  219. }
  220.  
  221. /*
  222.  * Kill forward by "n" words. Remember the location of dot. Move forward by
  223.  * the right number of words. Put dot back where it was and issue the kill
  224.  * command for the right number of characters. Bound to "M-D".
  225.  */
  226. delfword(f, n)
  227. {
  228.         register LINE   *dotp;
  229.         register int    doto;
  230.         long size;
  231.  
  232.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  233.         return(rdonly());    /* we are in read only mode    */
  234.         if (n < 0)
  235.                 return (FALSE);
  236.         if ((lastflag&CFKILL) == 0)     /* Clear kill buffer if */
  237.                 kdelete();              /* last wasn't a kill.  */
  238.         thisflag |= CFKILL;
  239.         dotp = curwp->w_dotp;
  240.         doto = curwp->w_doto;
  241.         size = 0;
  242.         while (n--) {
  243. #if    NFWORD
  244.         if (curwp->w_doto == llength(curwp->w_dotp)) {
  245.             if (forwchar(FALSE,1) == FALSE)
  246.                 return(FALSE);
  247.             ++size;
  248.         }
  249.  
  250.         while (inword() != FALSE) {
  251.             if (forwchar(FALSE,1) == FALSE)
  252.                 return(FALSE);
  253.             ++size;
  254.         }
  255.  
  256.                 while ((inword() == FALSE) &&
  257.                 (curwp->w_doto != llength(curwp->w_dotp))) {
  258.                         if (forwchar(FALSE, 1) == FALSE)
  259.                                 return (FALSE);
  260.                         ++size;
  261.                 }
  262. #else
  263.                 while (inword() == FALSE) {
  264.                         if (forwchar(FALSE, 1) == FALSE)
  265.                                 return (FALSE);
  266.                         ++size;
  267.                 }
  268.  
  269.                 while (inword() != FALSE) {
  270.                         if (forwchar(FALSE, 1) == FALSE)
  271.                                 return (FALSE);
  272.                         ++size;
  273.                 }
  274. #endif
  275.         }
  276.         curwp->w_dotp = dotp;
  277.         curwp->w_doto = doto;
  278.         return (ldelete(size, TRUE));
  279. }
  280.  
  281. /*
  282.  * Kill backwards by "n" words. Move backwards by the desired number of words,
  283.  * counting the characters. When dot is finally moved to its resting place,
  284.  * fire off the kill command. Bound to "M-Rubout" and to "M-Backspace".
  285.  */
  286. delbword(f, n)
  287. {
  288.         long size;
  289.  
  290.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  291.         return(rdonly());    /* we are in read only mode    */
  292.         if (n < 0)
  293.                 return (FALSE);
  294.         if ((lastflag&CFKILL) == 0)     /* Clear kill buffer if */
  295.                 kdelete();              /* last wasn't a kill.  */
  296.         thisflag |= CFKILL;
  297.         if (backchar(FALSE, 1) == FALSE)
  298.                 return (FALSE);
  299.         size = 0;
  300.         while (n--) {
  301.                 while (inword() == FALSE) {
  302.                         if (backchar(FALSE, 1) == FALSE)
  303.                                 return (FALSE);
  304.                         ++size;
  305.                 }
  306.                 while (inword() != FALSE) {
  307.                         if (backchar(FALSE, 1) == FALSE)
  308.                                 return (FALSE);
  309.                         ++size;
  310.                 }
  311.         }
  312.         if (forwchar(FALSE, 1) == FALSE)
  313.                 return (FALSE);
  314.         return (ldelete(size, TRUE));
  315. }
  316.  
  317. /*
  318.  * Return TRUE if the character at dot is a character that is considered to be
  319.  * part of a word. The word character list is hard coded. Should be setable.
  320.  */
  321. inword()
  322. {
  323.         register int    c;
  324.  
  325.         if (curwp->w_doto == llength(curwp->w_dotp))
  326.                 return (FALSE);
  327.         c = lgetc(curwp->w_dotp, curwp->w_doto);
  328.         if (c>='a' && c<='z')
  329.                 return (TRUE);
  330.         if (c>='A' && c<='Z')
  331.                 return (TRUE);
  332.         if (c>='0' && c<='9')
  333.                 return (TRUE);
  334.         if (c=='$' || c=='_')                   /* For identifiers      */
  335.                 return (TRUE);
  336.         return (FALSE);
  337. }
  338.  
  339. #if    WORDPRO
  340. fillpara(f, n)    /* Fill the current paragraph according to the current
  341.            fill column                        */
  342.  
  343. int f, n;    /* deFault flag and Numeric argument */
  344.  
  345. {
  346.     register int c;            /* current char durring scan    */
  347.     register int wordlen;        /* length of current word    */
  348.     register int clength;        /* position on line during fill    */
  349.     register int i;            /* index during word copy    */
  350.     register int newlength;        /* tentative new line length    */
  351.     register int eopflag;        /* Are we at the End-Of-Paragraph? */
  352.     register int firstflag;        /* first word? (needs no space)    */
  353.     register LINE *eopline;        /* pointer to line just past EOP */
  354.     register int dotflag;        /* was the last char a period?    */
  355.     char wbuf[NSTRING];        /* buffer for current word    */
  356.  
  357.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  358.         return(rdonly());    /* we are in read only mode    */
  359.     if (fillcol == 0) {    /* no fill column set */
  360.         mlwrite("No fill column set");
  361.         return(FALSE);
  362.     }
  363.  
  364.     /* record the pointer to the line just past the EOP */
  365.     gotoeop(FALSE, 1);
  366.     eopline = lforw(curwp->w_dotp);
  367.  
  368.     /* and back top the beginning of the paragraph */
  369.     gotobop(FALSE, 1);
  370.  
  371.     /* initialize various info */
  372.     clength = curwp->w_doto;
  373.     if (clength && curwp->w_dotp->l_text[0] == TAB)
  374.         clength = 8;
  375.     wordlen = 0;
  376.     dotflag = FALSE;
  377.  
  378.     /* scan through lines, filling words */
  379.     firstflag = TRUE;
  380.     eopflag = FALSE;
  381.     while (!eopflag) {
  382.         /* get the next character in the paragraph */
  383.         if (curwp->w_doto == llength(curwp->w_dotp)) {
  384.             c = ' ';
  385.             if (lforw(curwp->w_dotp) == eopline)
  386.                 eopflag = TRUE;
  387.         } else
  388.             c = lgetc(curwp->w_dotp, curwp->w_doto);
  389.  
  390.         /* and then delete it */
  391.         ldelete(1L, FALSE);
  392.  
  393.         /* if not a separator, just add it in */
  394.         if (c != ' ' && c != '\t') {
  395.             dotflag = (c == '.');        /* was it a dot */
  396.             if (wordlen < NSTRING - 1)
  397.                 wbuf[wordlen++] = c;
  398.         } else if (wordlen) {
  399.             /* at a word break with a word waiting */
  400.             /* calculate tantitive new length with word added */
  401.             newlength = clength + 1 + wordlen;
  402.             if (newlength <= fillcol) {
  403.                 /* add word to current line */
  404.                 if (!firstflag) {
  405.                     linsert(1, ' '); /* the space */
  406.                     ++clength;
  407.                 }
  408.                 firstflag = FALSE;
  409.             } else {
  410.                 /* start a new line */
  411.                 lnewline();
  412.                 clength = 0;
  413.             }
  414.  
  415.             /* and add the word in in either case */
  416.             for (i=0; i<wordlen; i++) {
  417.                 linsert(1, wbuf[i]);
  418.                 ++clength;
  419.             }
  420.             if (dotflag) {
  421.                 linsert(1, ' ');
  422.                 ++clength;
  423.             }
  424.             wordlen = 0;
  425.         }
  426.     }
  427.     /* and add a last newline for the end of our new paragraph */
  428.     lnewline();
  429.     return(TRUE);
  430. }
  431.  
  432. killpara(f, n)    /* delete n paragraphs starting with the current one */
  433.  
  434. int f;    /* default flag */
  435. int n;    /* # of paras to delete */
  436.  
  437. {
  438.     register int status;    /* returned status of functions */
  439.  
  440.     while (n--) {        /* for each paragraph to delete */
  441.  
  442.         /* mark out the end and beginning of the para to delete */
  443.         gotoeop(FALSE, 1);
  444.  
  445.         /* set the mark here */
  446.             curwp->w_markp = curwp->w_dotp;
  447.             curwp->w_marko = curwp->w_doto;
  448.  
  449.         /* go to the beginning of the paragraph */
  450.         gotobop(FALSE, 1);
  451.         curwp->w_doto = 0;    /* force us to the beginning of line */
  452.     
  453.         /* and delete it */
  454.         if ((status = killregion(FALSE, 1)) != TRUE)
  455.             return(status);
  456.  
  457.         /* and clean up the 2 extra lines */
  458.         ldelete(2L, TRUE);
  459.     }
  460.     return(TRUE);
  461. }
  462.  
  463.  
  464. /*    wordcount:    count the # of words in the marked region,
  465.             along with average word sizes, # of chars, etc,
  466.             and report on them.            */
  467.  
  468. wordcount(f, n)
  469.  
  470. int f, n;    /* ignored numeric arguments */
  471.  
  472. {
  473.     register LINE *lp;    /* current line to scan */
  474.     register int offset;    /* current char to scan */
  475.     long size;        /* size of region left to count */
  476.     register int ch;    /* current character to scan */
  477.     register int wordflag;    /* are we in a word now? */
  478.     register int lastword;    /* were we just in a word? */
  479.     long nwords;        /* total # of words */
  480.     long nchars;        /* total number of chars */
  481.     int nlines;        /* total number of lines in region */
  482.     int avgch;        /* average number of chars/word */
  483.     int status;        /* status return code */
  484.     REGION region;        /* region to look at */
  485.  
  486.     /* make sure we have a region to count */
  487.         if ((status = getregion(®ion)) != TRUE)
  488.                 return(status);
  489.     lp = region.r_linep;
  490.     offset = region.r_offset;
  491.     size = region.r_size;
  492.  
  493.     /* count up things */
  494.     lastword = FALSE;
  495.     nchars = 0L;
  496.     nwords = 0L;
  497.     nlines = 0;
  498.     while (size--) {
  499.  
  500.         /* get the current character */
  501.         if (offset == llength(lp)) {    /* end of line */
  502.             ch = '\n';
  503.             lp = lforw(lp);
  504.             offset = 0;
  505.             ++nlines;
  506.         } else {
  507.             ch = lgetc(lp, offset);
  508.             ++offset;
  509.         }
  510.  
  511.         /* and tabulate it */
  512.         wordflag = ((ch >= 'a' && ch <= 'z') ||
  513.                 (ch >= 'A' && ch <= 'Z') ||
  514.                 (ch >= '0' && ch <= '9') ||
  515.                 (ch == '$' || ch == '_'));
  516.         if (wordflag == TRUE && lastword == FALSE)
  517.             ++nwords;
  518.         lastword = wordflag;
  519.         ++nchars;
  520.     }
  521.  
  522.     /* and report on the info */
  523.     if (nwords > 0L)
  524.         avgch = (int)((100L * nchars) / nwords);
  525.     else
  526.         avgch = 0;
  527.  
  528.     mlwrite("Words %D Chars %D Lines %d Avg chars/word %f",
  529.         nwords, nchars, nlines + 1, avgch);
  530.     return(TRUE);
  531. }
  532. #endif
  533.